package com.core.sdk.ui.adapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import com.core.sdk.ui.holder.BaseViewHolder;
import com.core.sdk.ui.holder.IViewHolder;

@SuppressWarnings("javadoc")
public abstract class MyBaseAdapter<DATA, STATE> extends BaseAdapter {

	protected final String TAG = this.getClass().getSimpleName();
	private final ArrayList<AdapterItem<DATA, STATE>> mData = new ArrayList<AdapterItem<DATA, STATE>>();
	private HashMap<String, ArrayList<Integer>> mViewTypeMap = new HashMap<String, ArrayList<Integer>>();
	private SparseArray<IViewHolder<DATA, STATE>> mHolderList = new SparseArray<IViewHolder<DATA, STATE>>();
	private Context context = null;
	private LayoutInflater mInflater = null;
	private final ConcurrentHashMap<String, IViewHolder<DATA, STATE>> viewMap = new ConcurrentHashMap<String, IViewHolder<DATA, STATE>>();
	
	protected abstract void onInitViewType();

	protected abstract BaseViewHolder<DATA, STATE> onCreateViewHolder(View view,Context act);

	protected abstract void onDestory();

	public MyBaseAdapter(Context act) {
		super();
		this.context = act;
		mInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		onInitViewType();
	}

	protected void addViewType(Class<DATA> c, int layout) {
		String key = c.getName();
		if(mViewTypeMap.containsKey(key)){
			mViewTypeMap.get(key).add(layout);
		}else{
			ArrayList<Integer> list = new ArrayList<Integer>();
			list.add(layout);
			mViewTypeMap.put(key, list);
		}
	}

	@Override
	public int getCount() {
		return mData.size();
	}

	@Override
	public AdapterItem<DATA, STATE> getItem(int arg0) {
		return mData.get(arg0);
	}

	@Override
	public long getItemId(int arg0) {
		return arg0;
	}

	@SuppressWarnings("unchecked")
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		BaseViewHolder<DATA, STATE> holder = null;
		if (convertView == null) {
			convertView = inflateView(position, convertView, parent);
			holder = createViewHolder(convertView);
			convertView.setTag(holder);
			viewMap.put(holder.toString(), holder);
		} else {
			holder = (BaseViewHolder<DATA, STATE>) convertView.getTag();
		}
		holder.setPosIndex(position);
		AdapterItem<DATA, STATE> item = getItem(position);
		holder.setItem(item);
		mHolderList.put(position, holder);
		return convertView;
	}
	
	private AdapterItem<DATA, STATE> convertDataToAdapterItem(DATA data, STATE state){
		if (data == null)
			return null;
		return new AdapterItem<DATA, STATE>(data, state);
	}
	
	private List<AdapterItem<DATA, STATE>> convertDataListToAdapterItemList(List<DATA> datas,List<STATE> states){
		List<AdapterItem<DATA, STATE>> list = new ArrayList<AdapterItem<DATA, STATE>>();
		for (int i = 0; i < datas.size(); i++) {
			AdapterItem<DATA, STATE> item = convertDataToAdapterItem(datas.get(i),states.get(i));
			if(item != null){
				list.add(item);
			}
		}
		return list;
	}

	public AdapterItem<DATA, STATE> addItem(DATA data, STATE state) {
		return addItem(mData.size(),data,state);
	}
	
	public AdapterItem<DATA, STATE> addItem(int index,DATA data, STATE state) {
		AdapterItem<DATA, STATE> adapterItem = convertDataToAdapterItem(data,state);
		if(adapterItem != null)
			mData.add(index,adapterItem);
		return adapterItem;
	}
	
	public AdapterItem<DATA, STATE> addItem(DATA data, STATE state, OnAdapterItemStateChangeListener<DATA, STATE> listener) {
		AdapterItem<DATA, STATE> item = addItem(data, state);
		if (item != null)
			item.setOnAdapterItemStateChangeListener(listener);
		return item;
	}
	
	public List<AdapterItem<DATA, STATE>> addItems(int index,List<DATA> datas,List<STATE> states){
		List<AdapterItem<DATA, STATE>> items = convertDataListToAdapterItemList(datas,states);
		mData.addAll(index,items);
		return items;
	}	

//	public void addItem(AdapterItem<DATA, STATE> item) {
//		if (item == null || item.getData() == null)
//			return;
//		if (!(item.getState() instanceof Void) && item.getState() == null)
//			return;
//		mData.add(item);
//	}

	public void delItem(AdapterItem<DATA, STATE> item) {
		if (item == null)
			return;
		mData.remove(item);
	}

	public AdapterItem<DATA, STATE> delItem(int position) {
		if (position >= mData.size())
			return null;
		AdapterItem<DATA, STATE> item = mData.remove(position);
		return item;
	}

	public void clearItems() {
		mData.clear();
	}

	private BaseViewHolder<DATA, STATE> createViewHolder(View view) {
		BaseViewHolder<DATA, STATE> holder = onCreateViewHolder(view,this.context);
		holder.initViews();
		return holder;
	}

	private View inflateView(int position, View convertView, ViewGroup parent) {
		int resource = getResourceId(position);
		View v = convertView;
		if (convertView == null) {
			v = mInflater.inflate(resource, parent, false);
		}
		return v;
	}

	private Integer getResourceId(int position) {
		AdapterItem<DATA, STATE> item = getItem(position);
		ArrayList<Integer> styleList = getResourceId(item.getData());
		return styleList.get(getStyleIndex());
	}
	
	private int mStyleIndex = 0;
	protected int getStyleIndex(){
		return mStyleIndex;
	}
	public final void setStyleIndex(int styleIndex){
		this.mStyleIndex = styleIndex;
	}

	private ArrayList<Integer> getResourceId(DATA data) {
		return mViewTypeMap.get(data.getClass().getName());
	}

	protected Context getMyContext() {
		return this.context;
	}

	/**
	 * 在Activity销毁的时候，必须要手动调用
	 */
	public void destory() {
		try {
			onDestory();
		} catch (Exception e) {
			e.printStackTrace();
		}
		for (IViewHolder<DATA, STATE> h : viewMap.values()) {
			h.destroy();
		}
		mHolderList.clear();
		viewMap.clear();
		mViewTypeMap.clear();
		System.gc();
	}

	public ArrayList<AdapterItem<DATA, STATE>> getItems() {
		ArrayList<AdapterItem<DATA, STATE>> items = new ArrayList<AdapterItem<DATA, STATE>>();
		items.addAll(mData);
		return items;
	}

	public void onPrepareNotifyDataSetChanged() {
	}

	public void onPostNotifyDataSetChanged() {
	}

	@Override
	public void notifyDataSetChanged() {
		onPrepareNotifyDataSetChanged();
		super.notifyDataSetChanged();
		onPostNotifyDataSetChanged();
	}
	//获取Holder
	public IViewHolder<DATA, STATE> getViewHolder(int position){
		return mHolderList.get(position, null);
	}
	
	@Deprecated
	public static final void printStatck(){
		   Throwable ex = new Throwable();
	        StackTraceElement[] es = ex.getStackTrace();
	        if (es != null) {
	            for (int i = 0; i < es.length; i++) {
	                StackTraceElement item = es[i];
	                String gg = item.getClassName()+"->"+item.getMethodName()+" line:"+item.getLineNumber();
	                System.out.println(gg);
	            }
	        }
	}
}
